package Code.Objects.Characters.Enemies.Basic;

import org.jrabbit.base.graphics.transforms.Vector2d;
import org.jrabbit.base.managers.ResourceManager;
import org.jrabbit.standard.game.graphics.skins.animation.AnimatedSkin;

import Code.Basic.Entity.GenericCharacter;

public abstract class MeleeCharacter extends MobileCharacter
{
	protected GenericCharacter target;
	
	protected double FAR_RADIUS = 750;
	protected double MELEE_RADIUS = 150;
	protected double attackOffset;
	protected double attackOffsetBase = 180;
	protected double attackOffsetTimer;
	protected double attackOffsetInterval = 30000;
	
	protected double modeTimer;
	protected double modeCheckInterval;
	int mode;
	protected static final int MODE_FAR = 0;
	protected static final int MODE_MIDDLE = 1;
	protected static final int MODE_MELEE = 2;

	public MeleeCharacter(String filepath)
	{
		super(filepath);
	}

	public MeleeCharacter(AnimatedSkin skin)
	{
		super(skin);
	}
	
	public void setTarget(GenericCharacter t)
	{
		target = t;
	}
	
	public GenericCharacter getTarget()
	{
		return target;
	}
	
	public void attackMovement(int time)
	{
		if(target.isDead())
		{
			target = null;
		}
		else
		{
			Vector2d diff = target.location().difference(location);
			double angle = diff.direction();
			
			modeTimer += time;
			if(modeTimer >= modeCheckInterval)
			{
				modeTimer -= modeCheckInterval;
				
				double distance = diff.magnitude();
				if(distance > FAR_RADIUS)
				{
					mode = MODE_FAR;
				}
				else if(distance < MELEE_RADIUS)
				{
					mode = MODE_MELEE;
				}
				else
				{
					mode = MODE_MIDDLE;
				}
			}
			
			attackOffsetTimer += time;
			if(attackOffsetTimer >= attackOffsetInterval)
			{
				attackOffsetTimer -= attackOffsetInterval;
				attackOffset = (ResourceManager.random().nextDouble() - 0.5) * attackOffsetBase;
			}
			
			switch(mode)
			{
				case MODE_FAR: rotateAndMoveTowards(angle); break;
				case MODE_MIDDLE: rotateAndMoveTowards(angle + attackOffset); break;
				case MODE_MELEE: rotateTowards(angle); attack(time, angle); break;
			}
		}
	}
	
	public abstract void attack(double time, double angle);
	
	public void wander(int time)
	{
		attackOffsetTimer += time;
		if(attackOffsetTimer >= attackOffsetInterval)
		{
			attackOffsetTimer -= attackOffsetInterval;
			attackOffset = (ResourceManager.random().nextDouble()) * 360;
		}
		rotateAndMoveTowards(attackOffset);
	}
	
	public void update(int time)
	{
		super.update(time);
		if(target != null)
		{
			attackMovement(time);
		}
		else
		{
			wander(time);
		}
	}
}
